<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>监视属性</title>
    <script type="text/javascript" src="../js/vue.js"></script> <!-- vue引入 -->
    <script type="text/javascript">
        Vue.config.productionTip=false; //阻止vue在启动时产生提示
    
        /*
            监视属性watch
                1.当被监视的属性变化时，回调函数自动调用，进行相关操作
                2.监视的属性必须存在，才能进行监视
                3.监视的两种写法
                    (1) new Vue时传入watch配置
                    (2) 通过vm.$watch监视
            
            深度监视：
                1.Vue中的watch默认不检测对象内部值的改变(一层)
                2.配置deep:true可以监视对象内部的值改变(多层)
                备注：
                    (1) Vue自身可以监视对象内部值的改变，但Vue提供的watch默认不可以
                    (2) 使用watch时根据数据的具体结构，决定是否采用深度监视
            
            computed和watch之间的区别
                1.computed能完成的功能，watch都可以完成。
                2.watch能完成的功能，computed不一定能完成，如：watch可以进行一般操作。
            两个重要的小原则
                1.所被Vue管理的函数，最好写成普通函数"function(){}"，这样this的指向才是vm或巨剑实列对象。
                2.所有不被Vue所管理的函数(定时器的回调、ajax的回调函数等、Promise的回调函数)，最好写成箭头函数，
                    这样this的指向才是vm或组件实例对象。
        */
        const vm = new Vue({
            //el:'#container'，
            data: {
                isHot:true,
                numbers: {
                    a:1
                    ,b:1
                },
                window //也可以直接把window放到data里面共给vm使用,常规写法 window: window
            },
            methods: {
                toggleWeather(event){ //切换天气事件函数
                    this.isHot = !this.isHot;
                } 
            },
            computed: {  //计算属性块定义
                //计算属性、简写方式
                weatherInfo() {
                    return this.isHot? '炎热': '凉爽';
                }
            },
            watch: { //监视属性块、关键字：watch、第一种写法
                'isHot': { //监视的属性、也可以直接isHot不用加引号, 同时也可以监视weatherInfo的计算属性,
                    immediate: true, //true:进入页面立即触发handler, false: 只有参数发生变化时触发handler,默认false
                    handler(newValue, oldValue) {
                        console.log('isHot被修改了，新值：%s，旧值：%s', newValue, oldValue);
                    }
                },
                
                /*
                isHot: function(newValue, oldValue) { //简写方式、简写方式不能使用immediate: true等属性；
                        console.log('isHot被修改了，新值：%s，旧值：%s', newValue, oldValue);
                },*/
                
                /*
                'numbers':{ //该方式只能监视到对象变化、但不能监视到具体某个属性变化
                    immediate: true,
                    deep:true, //深度监视、监视对象属性中的属性值发生变化、true检测 false不检测、默认false
                    handler(newValue, oldValue){
                        console.log('numbers被改变了', newValue, oldValue); //测试结果、new和old都是一样的，这里无法监视到具体哪个属性变化
                    }
                }*/
                
            }
        });

        /*
        vm.$watch('isHot',{ //第二种写法
            immediate: true,
            handler(newValue, oldValue) {
                console.log('isHot被修改了，新值：%s，旧值：%s', newValue, oldValue);
            }
        });
        
        vm.$watch('isHot',function(newValue, oldValue){ //简写、简写方式不能使用immediate: true等属性；
            console.log('isHot被修改了，新值：%s，旧值：%s', newValue, oldValue);
        });
        */


        //监视对象中的所有属性变化
        for(let numbersKey in vm._data.numbers){ //循环绑定所有属性的监视
            let key = 'numbers.'+numbersKey;
            vm.$watch(key,{  //对象名.属性名
                immediate: true, //true:进入页面立即触发handler, false: 只有参数发生变化时触发handler,默认false
                handler(newValue, oldValue) {
                    console.log('对象中的属性%s发生变化了, 新值：%s，旧值：%s', key, newValue, oldValue);
                }
            });
        }

        window.onload = function() { //页面加载完成在加载该方法
            vm.$mount('#container');
        }
    </script>
</head>
<body>
    <!-- 
       
    -->
    <div id="container">
       <h2>今天天气{{weatherInfo}}</h2>
       <button @click="toggleWeather($event)">切换天气(方式1)</button>
       <button @click="isHot = !isHot">切换天气(方式2)</button><br><br> <!-- 简单语句可以使用这个、语句多的话不推荐该方式，建议使用第1种 -->
       <button @click="window.alert('我是window弹框')">引用window的弹框</button><br><br> <!-- 前提必须在vm data里面把window属性定义好 -->
       多结构监视numbers.a变化：<input type="text" v-model="numbers.a"><br>
       多结构监视numbers.b变化：<input type="text" v-model="numbers.b">
    </div>
</body>
</html>